#include "ctrl_data.h"
#include "esp_log.h"
#include "stdbool.h"
#define SEND_TAG "SEND"
float max_humi = MAX_HUMI;
float min_humi = MIN_HUMI;
float max_temp = MAX_TEMP;
float min_temp = MIN_TEMP;
float low_power = LOWPOW_ALARM;

// 温湿度、电压的报警状态
alarm_state temp_alarm = cancel;
alarm_state humi_alarm = cancel;
alarm_state last_temp_alarm = cancel;
alarm_state last_humi_alarm = cancel;
bool last_lowpower_alarm = false;
bool lowpower_alarm = false;


static void check_alarm(float temperature,float humidity,float voltage)
{

    bool is_first_boot = false;
    esp_err_t err = read_first_data_boot_flag(&is_first_boot);
    if(err!= ESP_OK)
    {
        ESP_LOGE(SEND_TAG,"Error reading first boot flag from NVS flash");
    }
    if(is_first_boot)
    {
        ESP_LOGI(SEND_TAG,"First boot detected, initializing limits");
        aliot_post_property_float("temp_alarm",temp_alarm);
        aliot_post_property_float("humi_alarm",humi_alarm);
        aliot_post_property_float("lowpower_alarm",lowpower_alarm);
    }
    if(temperature > max_temp){
        temp_alarm = upperalarm;
    }
    else if(temperature < min_temp){
        temp_alarm = loweralarm;
    }else{
        temp_alarm = cancel;
    }
 

    if(humidity > max_humi){
        humi_alarm = upperalarm;
    }
    else if(humidity < min_humi){
        humi_alarm = loweralarm;
    }else{
        humi_alarm = cancel;
    }

    if(voltage < low_power)
    {
        lowpower_alarm = true;
    }
    else{
        lowpower_alarm = false;
    }
    
    if(temp_alarm!=last_temp_alarm)
    {
        ESP_LOGI(SEND_TAG, "Temperature alarm status changed, alarm update");
        aliot_post_property_float("temp_alarm",temp_alarm);
        last_temp_alarm = temp_alarm;
    }
    
    if(humi_alarm!=last_humi_alarm)
    {
        ESP_LOGI(SEND_TAG, "Humidity alarm status changed, alarm update");
        aliot_post_property_float("humi_alarm",humi_alarm);
        last_humi_alarm = humi_alarm;
    }

    if(lowpower_alarm!=last_lowpower_alarm)
    {
        ESP_LOGI(SEND_TAG, "Low power alarm status changed, alarm update");
        aliot_post_property_float("lowpower_alarm",lowpower_alarm);
        last_lowpower_alarm = lowpower_alarm;
    }
    
}


static void init_ctrl_data(float temperature,float humidity,float pow_percent)
{
    //是否是第一次启动设备 如果第一次启动 则赋给默认值
    bool is_first_boot = false;
    esp_err_t err = read_first_data_boot_flag(&is_first_boot);
    if(is_first_boot)
    {
        //将初始化数据写入NVS flash中
        err = write_data_to_nvs(max_temp, min_temp, max_humi, min_humi,low_power);
        ESP_LOGI(SEND_TAG,"First boot detected, initializing limits");
        //发布初始阈值
        aliot_post_property_float("max_temp",max_temp);
        aliot_post_property_float("min_temp",min_temp);
        aliot_post_property_float("max_humi",max_humi);
        aliot_post_property_float("min_humi",min_humi);
        aliot_post_property_float("low_power",low_power);
    }
    else
    {
        err = write_first_data_boot_flag(false);
        if(err!= ESP_OK)
        {
            ESP_LOGE(SEND_TAG,"Error writing first boot flag to NVS flash");
        }
        err = read_data_from_nvs(&max_temp, &min_temp, &max_humi, &min_humi,&low_power);
        if(err!= ESP_OK)
        {
            ESP_LOGE(SEND_TAG,"Error reading data from NVS flash");
        }
            //发布非初始化阈值
        aliot_post_property_float("max_temp",max_temp);
        aliot_post_property_float("min_temp",min_temp);
        aliot_post_property_float("max_humi",max_humi);
        aliot_post_property_float("min_humi",min_humi);
        aliot_post_property_float("low_power",low_power);
    
        check_alarm(temperature,humidity,pow_percent);
    }
    
}
//发布控制数据
void post_ctrl_data(esp_mqtt_event_handle_t data)
{
    float temperature = SHT40_readTemp();
    float humidity = SHT40_readHumi();
    float pow_percent = ADC_read_voltage();
    if(strstr(data->topic,"/property/set"))
        {
            cJSON * property_js = cJSON_Parse(data->data);
            cJSON * params_js = cJSON_GetObjectItem(property_js,"params");
            
            if(params_js)
            {
                //温湿度的上下限阈值以及电压低阈值
                cJSON * max_temp_js =  cJSON_GetObjectItem(params_js,"max_temp"); 
                cJSON * min_temp_js = cJSON_GetObjectItem(params_js,"min_temp"); 
                cJSON * max_humi_js =  cJSON_GetObjectItem(params_js,"max_humi"); 
                cJSON * min_humi_js = cJSON_GetObjectItem(params_js,"min_humi");
                cJSON * low_power_js = cJSON_GetObjectItem(params_js,"low_power");
                //温湿度,电压阈值的警告 
                cJSON * humi_alarm_js = cJSON_GetObjectItem(params_js,"humi_alarm");  
                cJSON * temp_alarm_js = cJSON_GetObjectItem(params_js,"temp_alarm");
                cJSON * lowpower_alarm_js = cJSON_GetObjectItem(params_js,"lowpower_alarm");  
                //给 cJSON_GetNumberValue强转成枚举类型
                if(humi_alarm_js)  humi_alarm = (alarm_state)cJSON_GetNumberValue(humi_alarm_js);
                if(temp_alarm_js)  temp_alarm = (alarm_state)cJSON_GetNumberValue(temp_alarm_js);
                
                if (max_temp_js) max_temp = cJSON_GetNumberValue(max_temp_js);
                if (min_temp_js) min_temp = cJSON_GetNumberValue(min_temp_js);
                if (max_humi_js) max_humi = cJSON_GetNumberValue(max_humi_js);
                if (min_humi_js) min_humi = cJSON_GetNumberValue(min_humi_js);
                //拿到电压阈值和预警信息
                if(low_power_js)  low_power = cJSON_GetNumberValue(low_power_js);
                if (lowpower_alarm_js) lowpower_alarm = cJSON_IsTrue(lowpower_alarm_js);
                //将更新后的数据写入NVS flash中
                 write_data_to_nvs(max_temp, min_temp, max_humi, min_humi,low_power) ;

                // 发布更新后的阈值
                if(max_temp<min_temp || max_humi<min_humi)
                {
                    ESP_LOGE(SEND_TAG,"Invalid limits, please check the limits");
                }
                else
                {
                aliot_post_property_float("max_temp", max_temp);
                aliot_post_property_float("min_temp", min_temp);
                aliot_post_property_float("max_humi", max_humi);
                aliot_post_property_float("min_humi", min_humi);
                aliot_post_property_float("low_power", low_power);
                check_alarm(temperature,humidity,pow_percent);
                ESP_LOGI(SEND_TAG, "Updated limits - Max Temp: %.2f, Min Temp: %.2f, Max Humidity: %.2f, Min Humidity: %.2f, Low Power: %.2f, Is Low Power Alarm? : %s",max_temp, min_temp, max_humi, min_humi, low_power,lowpower_alarm?"warning":"normal");
                }
            
            }
            aliot_property_ack(200,"success");
            cJSON_Delete(property_js);   
        }
}
void mqtt_read_data()
{
    float temperature = SHT40_readTemp();
    float humidity = SHT40_readHumi();
    float pow_percent = ADC_read_voltage();;
    init_ctrl_data(temperature,humidity,pow_percent);
    ESP_LOGI(SEND_TAG, "Updated limits - Max Temp: %.2f, Min Temp: %.2f, Max Humidity: %.2f, Min Humidity: %.2f, Low Power: %.2f, Is Low Power Alarm? : %s",max_temp, min_temp, max_humi, min_humi, low_power,lowpower_alarm?"warning":"normal");         
    while (1)
    {
        temperature = SHT40_readTemp();
        humidity = SHT40_readHumi();
        pow_percent =ADC_read_voltage();
        temperature = (int)(temperature * 100 + 0.5) / 100.0; //四舍五入 保留两位小数
        humidity = (int)(humidity * 100 + 0.5) / 100.0;
        pow_percent= (int)(pow_percent * 100 + 0.5) / 100.0;
        if(is_connected_mqtt())
        {
            ESP_LOGI(SEND_TAG,"CurrentTemperature:%.2f",temperature);
            ESP_LOGI(SEND_TAG,"CurrentHumidity:%.2f",humidity);
            ESP_LOGI(SEND_TAG,"CurrentVoltage:%.2f",pow_percent);
            aliot_post_property_float("CurrentTemperature",temperature);
            aliot_post_property_float("CurrentHumidity",humidity);
            aliot_post_property_float("battery_percentage",pow_percent);
            
        }
        else {ESP_LOGE(SEND_TAG,"ERROR: MQTT NOT CONNECTED");}
        vTaskDelay(pdMS_TO_TICKS(15000));
    }
}

